<script lang="ts" setup>
import { watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
import * as echarts from 'echarts'

interface Props {
  chartId: string
  legend?: any
  yUnit: string
  series: any
  source: any
  yAxis?: any
  xAxis?: any
  grid?: any
  intervalCeil?: number
  showYunit?: boolean
  tooltip?: any
  dataZoom?: any
  animation?: boolean
  title?: any
}

const props = withDefaults(defineProps<Props>(), {
  chartId: 'chart-line',
  legend: {},
  yUnit: '',
  title: {},
  series: [],
  source: [],
  yAxis: {},
  xAxis: {},
  grid: {},
  intervalCeil: 0,
  showYunit: true,
  tooltip: {},
  dataZoom: undefined,
  animation: true
})

watch(
  () => props.source,
  () => {
    updateChart()
  }
)

watch(
  () => props.dataZoom,
  () => {
    option.dataZoom = props.dataZoom
    updateChart()
  },
  {
    deep: true
  }
)

watch(
  () => props.yAxis,
  () => {
    option.yAxis = {
      ...option.yAxis,
      ...props.yAxis
    }
    updateChart()
  }
)

watch(
  () => props.series,
  () => {
    option.series = formatterSeries()
    updateChart()
  },
  { deep: true }
)

const formatterSeries = () => {
  return props.series.map((item: any) => {
    return {
      type: item.type || 'line',
      datasetIndex: 0,
      smooth: true,
      showSymbol: true,
      areaStyle: {
        color: {
          type: 'linear',
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: item.colorStops.map((cs: string, csi: number) => {
            return {
              offset: csi,
              color: cs
            }
          }),
          global: false // 缺省为 false
        }
      },
      ...item
    }
  })
}

const option: any = {
  graphic: {
    type: 'text',
    left: 'center',
    top: 'center',
    style: {
      text: '暂无数据',
      fontStyle: 'normal',
      fontWeight: 'normal',
      fontSize: 14,
      fill: 'rgba(174, 177, 189, 1)'
    }
  },
  title: props.title,
  dataZoom: props.dataZoom,
  legend: {
    show: true,
    icon: 'circle',
    itemWidth: 6,
    itemHeight: 6,
    textStyle: {
      color: '#707479',
      fontSize: 14
    },
    top: 0,
    right: 0,
    ...props.legend
  },
  tooltip: {
    trigger: 'axis',
    formatter: function (params: any) {
      let str = params[0].name + '<br>'
      params.forEach((item: any) => {
        const key = item?.encode?.y
        str += `${item.marker}${item.seriesName}: ${
          item.value[item.dimensionNames[key]]
        }${props.yUnit}<br>`
      })
      if (params[0].data.isShowTime) {
        str += `${params[0].data.timeName}: ${params[0].data.createTime}`
      }
      return str
    },
    axisPointer: {
      show: true,
      type: 'cross',
      label: {
        formatter: function (params: any) {
          return params.axisDimension === 'y'
            ? params.value.toFixed(2) + props.yUnit
            : params.value
        }
      }
    },
    ...props.tooltip
  },
  grid: {
    left: 40,
    right: 0,
    top: 30,
    bottom: 0,
    containLabel: true,
    ...props.grid
  },
  dataset: {
    source: []
  },
  xAxis: {
    type: 'category',
    splitLine: { show: false },
    axisLabel: {
      show: true,
      color: '#707479',
      fontSize: 14,
      rotate: 45
    },
    axisTick: {
      show: false
    },
    nameTextStyle: {},
    ...props.xAxis
  },
  yAxis: {
    nameTextStyle: {
      color: '#707479',
      fontSize: 14
    },
    type: 'value',
    min: 0,
    max: 100,
    splitNumber: 2,
    axisLabel: {
      color: '#707479',
      interval: 0,
      fontSize: 14,
      formatter: function (value: any) {
        const roundedValue = value >= 1 ? Math.round(value) : value
        return `${roundedValue}${props.showYunit ? props.yUnit : ''}`
      },
      textStyle: {}
    },
    splitLine: {
      show: true,
      lineStyle: {
        color: 'rgba(240, 240, 240, 1)',
        type: 'dashed'
      }
    },
    ...props.yAxis
  },
  series: formatterSeries(),
  animation: props.animation
}

let echartsInstance: any = null

const disposeChart = () => {
  if (echartsInstance) {
    echartsInstance?.dispose()
  }
}

const renderChart = () => {
  const chartDom = document.getElementById(props.chartId) as HTMLElement
  disposeChart()
  echartsInstance = echarts.init(chartDom)
}

const updateChart = () => {
  option.dataset.source = props.source
  if (props.intervalCeil !== 0) {
    option.xAxis.axisLabel.interval =
      props.source.length > props.intervalCeil
        ? Math.floor(props.source.length / props.intervalCeil)
        : 0
  }

  option.yAxis.name = props.source.length ? props.yAxis.name : ''
  option.graphic.style.text = props.source.length ? '' : '暂无数据'
  echartsInstance?.clear()
  if (option && typeof option === 'object') {
    echartsInstance?.setOption(option)
  }
}

onMounted(() => {
  nextTick(() => {
    renderChart()
  })
})

onBeforeUnmount(() => {
  disposeChart()
})

defineExpose({ updateChart })
</script>

<template>
  <div :id="props.chartId" class="chart-line"></div>
</template>

<style lang="less" scoped>
.chart-line {
  height: 100%;
  min-height: 200px;
}
</style>
